#!/usr/bin/env python
#
# gui.py
#
# Version : 0.7
# Date : 20080520
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

# gui.py - administrator gui interface, run as part of skipolemonitor.
# This module is a part of the sm_gui package, and contains the function
# maingui() which is called from monitor.pyw to start the gui interface.
#
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

"""The function maingui() within this module runs the gui interface for Skipole Monitor

The gui consists of the main AppFrame which is defined here, and via NoteBook panel
it opens several panels for editing the hosts, setting up email and syslog
parameters and application options.

The gui uses the wxPython library which must be installed.
"""

import wx
import os
import time
import validate
import webserver
from net import *
from sm_gui import gui_globals
from sm_gui import syslog_setup
from sm_gui import email_setup
from sm_gui import options_setup
from sm_gui import front_tab
from sm_gui import host_group_tab
    

# ------------------ The Application Class

class App(wx.App):
    """Skipole Monitor Gui wx Application class."""

    def OnInit(self):
        """Display splash, check for errors, continue with main application"""
        self.splash = SMSplashScreen()
        self.splash.Show()
        # The splash screen is displayed, now check for any startup errors
        error_status, error_string = validate.error_value()
        if error_status:
            wx.MessageBox("ERROR: " + error_string,
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
            # So an error messager is displayed - now exit
            return True
        # No errors, continue with the main application
        time.sleep(2)
        self.frame = AppFrame(None, -1, "Skipole Monitor")
        self.frame.Centre(direction=wx.BOTH)
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True


#  ------------------ The initial SkipoleMonitor splash screen

class SMSplashScreen(wx.SplashScreen):
    """ Display the image splash.png as the startup splashscreen"""

    def __init__(self):
        # SCRIPTDIRECTORY is from the net module
        splash_image=os.path.join(SCRIPTDIRECTORY,'splash.png')
        bmp = wx.Image(splash_image, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        wx.SplashScreen.__init__(self, bmp,
                                 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
                                 2000, None, -1)
        return
        
        
#  ------------------ AppFrame including a tabbed notebook

class AppFrame(wx.Frame):
    """The main frame of the gui"""

    def __init__(self, parent, id, title):
        """Create the frame, and a tabbed notebook"""
        wx.Frame.__init__(self, parent, id, title, style=wx.DEFAULT_FRAME_STYLE ^ (wx.CLOSE_BOX))
        # Set the frame icon
        self.SetIcon(gui_globals.get_icon())
        # Create the panel for the frame
        self.frame_panel = wx.Panel(self)
        # Create the sizer for the frame
        self.frame_sizer=wx.BoxSizer(wx.VERTICAL)
        # Create a Tabbed Notebook
        self.TabbedNotebook=EditNotebook(self.frame_panel, -1)
        self.frame_sizer.Add(self.TabbedNotebook, 0, wx.ALIGN_LEFT)
        # Set up the status bar at the bottom of the frame
        self.init_statusbar()
        # Set the size to the panel, and frame
        self.frame_panel.SetSizer(self.frame_sizer)
        # Stop the frame manually reducing below the size set by the notebook
        self.frame_sizer.SetSizeHints(self)
        # Bind the Exit Button event from the skipole monitor panel to OnCloseMe method
        self.Bind(wx.EVT_BUTTON, self.OnCloseMe, self.TabbedNotebook.skipole_monitor_panel.exit_button)

    def init_statusbar(self):
        """Set up the status bar at the bottom of the frame"""
        self.statusbar = self.CreateStatusBar()
        self.statusbar.SetFieldsCount(2)
        self.set_polling_status()
        self.set_webserver_status()
        # Check poller and web status every two seconds
        self.status_checker = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnChecking, self.status_checker)
        self.status_checker.Start(2000, oneShot=False)

    def OnChecking(self, event):
        """Check the host statisticts"""
        self.set_polling_status()
        self.set_webserver_status()
        return

    def set_polling_status(self):
        """Set status bar polling status"""
        # net_cfg and HOST_STATS are from the net module
        minutes = "5 minutes"
        if net_cfg["POLL_INTERVAL"] == "60": minutes = "1 minute"
        if net_cfg["POLL_INTERVAL"] == "120": minutes = "2 minutes"
        if net_cfg["POLL_INTERVAL"] == "600": minutes = "10 minutes"
        self.statusbar.SetStatusText("Polling : %s : %i Hosts" % (minutes, HOST_STATS[0]), 0)
        return

    def set_webserver_status(self):
        """Set status bar webserver status"""
        if webserver.WEB_RUNNING:
            self.statusbar.SetStatusText("Web server : On : Port %s" % net_cfg["PORT"], 1)
        else:
            self.statusbar.SetStatusText("Web server : Stopped", 1)
        return

    def OnCloseMe(self, event):
        """Exit button has been pressed"""
        confirm_close=wx.MessageDialog(parent=self,
                                       message="This shuts down Skipole Monitor, are you sure?",
                                       caption="Exit Skipole Monitor",
                                       style=wx.YES_NO | wx.ICON_EXCLAMATION)
        result=confirm_close.ShowModal()
        confirm_close.Destroy()
        if result == wx.ID_YES:
            self.Close(True)
        return


# --------- EditNotebook Window which gives the tabs

class EditNotebook(wx.Notebook):
    """The Tabbed Notebook of the gui"""

    def __init__(self, parent, id):
        """Create the tabbed notebook, and each panel beneath each tab"""
        wx.Notebook.__init__(self, parent, id )
        # Set the first tab page as skipole_monitor_panel
        self.skipole_monitor_panel = front_tab.SkipoleMonitor(self)
        # Add skipole_monitor_panel to the SetupNotebook
        self.AddPage(self.skipole_monitor_panel, " Skipole Monitor ")
        # The host and groups configuration panel
        self.host_group_panel = host_group_tab.HostGroupSetup(self)
        # Add host_group_panel to the SetupNotebook
        self.AddPage(self.host_group_panel, " Hosts and Groups ")
        # Define the email config fields and buttons, and place them in email_panel
        self.email_panel = email_setup.EmailSetup(self)
        # Add email_panel to the SetupNotebook
        self.AddPage(self.email_panel, " Email Setup ")
        # Define the syslog config fields and buttons, and place them in syslog_panel
        self.syslog_panel = syslog_setup.SyslogSetup(self)
        # Add syslog_panel to the SetupNotebook
        self.AddPage(self.syslog_panel, " Syslog Setup ")
        # Define the options fields and buttons, and place them in options_panel
        self.options_panel = options_setup.OptionsSetup(self)
        # Add options_panel to the SetupNotebook
        self.AddPage(self.options_panel, " Options ")


# --------------- maingui - called from monitor.pyw and runs this gui

def maingui():
    """Called from monitor.py and starts the gui main loop"""
    app = App()
    app.MainLoop()


